import Vue from 'vue';
import Config from './config';
import axios from 'axios';
import download from 'downloadjs';

class Util {
    abp: any = window.abp;
    vm = new Vue({});

    loadScript(url: string) {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = url;
        document.body.appendChild(script);
    }

    title(title: string) {
        let appName = 'PANDX MULAN 通用管理系统';
        let page = this.abp.localization.localize(title, Config.localization.defaultLocalizationSourceName);
        window.document.title = appName + ' - ' + page;
    }

    inOf(arr: any[], targetArr: any) {
        let res = true;
        arr.forEach(item => {
            if (targetArr.indexOf(item) < 0) {
                res = false;
            }
        });
        return res;
    }

    oneOf(ele: any, targetArr: any[]) {
        return targetArr.indexOf(ele) >= 0;
    }

    showThisRoute(itAccess: any, currentAccess: any) {
        if (typeof itAccess === 'object' && Array.isArray(itAccess)) {
            return this.oneOf(currentAccess, itAccess);
        } else {
            return itAccess === currentAccess;
        }
    }

    getRouterObjByName(routers: any[], name?: string): any {
        if (!name || !routers || !routers.length) {
            return null;
        }
        let routerObj = null;
        for (let item of routers) {
            if (item.name === name) {
                return item;
            }
            routerObj = this.getRouterObjByName(item.children, name);
            if (routerObj) {
                return routerObj;
            }
        }
        return null;
    }

    toDefaultPage(routers: any[], name: string | undefined, route: any, next: any) {
        let len = routers.length;
        let i = 0;
        let notHandle = true;
        while (i < len) {
            if (routers[i].name === name && routers[i].children && routers[i].redirect === undefined) {
                route.replace({
                    name: routers[i].children[0].name,
                });
                notHandle = false;
                next();
                break;
            }
            i++;
        }
        if (notHandle) {
            next();
        }
    }

    handleTitle(vm: any, item: any) {
        if (typeof item.meta.title === 'object') {
            return vm.$t(item.title.i18n);
        } else {
            return item.meta.title;
        }
    }

    addOther(vm: Vue, name: string, params?: any) {
        vm.$store.commit('app/setCurrentPageName', name);
        let pathArr = this.setCurrentPath(vm, name);
        if (pathArr.length > 2) {
            vm.$store.commit('app/addOpenSubmenu', pathArr[1].name);
        }
        let openPageHasTag = (vm.$store.state.app.pageOpenedList as any[]).some(item => {
            return item.name === name;
        });
        if (!openPageHasTag) {
            this.openNewPage(
                vm,
                name,
                vm.$route.params || {},
                vm.$route.query || {},
            );
        }
        vm.$router.replace({
            name: name,
            params: params,
        });
    }

    closePage(vm: Vue, name: string) {
        vm.$store.commit('app/removeTag', name);
        vm.$store.commit('app/closePage', name);
        let pageOpenedList = vm.$store.state.app.pageOpenedList;
        localStorage.pageOpenedList = JSON.stringify(pageOpenedList);
        if (vm.$route.name === name) {
            let lastPageName = '';
            if (pageOpenedList.length > 1) {
                lastPageName = pageOpenedList[1].name;
            } else {
                lastPageName = pageOpenedList[0].name;
            }
            vm.$router.push({
                name: lastPageName,
            });
        }

    }

    setCurrentPath(vm: Vue, name?: string) {
        let title = '';
        let isOtherRouter = false;
        vm.$store.state.app.routers.forEach((item: any) => {
            if (item.children.length === 1) {
                if (item.children[0].name === name) {
                    title = this.handleTitle(vm, item);
                    if (item.name === 'otherRouter') {
                        isOtherRouter = true;
                    }
                }
            } else {
                item.children.forEach((child: any) => {
                    if (child.name === name) {
                        title = this.handleTitle(vm, child);
                        if (item.name === 'otherRouter') {
                            isOtherRouter = true;
                        }
                    }
                });
            }
        });
        let currentPathArr = [];
        if (name === 'home') {
            currentPathArr = [
                {
                    meta: {title: this.handleTitle(vm, this.getRouterObjByName(vm.$store.state.app.routers, 'home'))},
                    path: 'main/home',
                    name: 'home',
                },
            ];
        } else if (((name as string).indexOf('app.less') >= 0 || isOtherRouter) && name !== 'home') {
            currentPathArr = [
                {
                    meta: {title: this.handleTitle(vm, this.getRouterObjByName(vm.$store.state.app.routers, 'home'))},
                    path: 'main/home',
                    name: 'home',
                },
                {
                    meta: {title: title},
                    path: '',
                    name: name,
                },
            ];
        } else {
            let currentPathObj = vm.$store.state.app.routers.filter((item: any) => {
                if (item.children.length <= 1) {
                    return item.children[0].name === name || item.name === name;
                } else {
                    let i = 0;
                    let childArr = item.children;
                    let len = childArr.length;
                    while (i < len) {
                        if (childArr[i].name === name) {
                            return true;
                        }
                        i++;
                    }
                    return false;
                }
            })[0];
            if (currentPathObj.children && currentPathObj.children.length <= 1 && currentPathObj.name === 'home') {
                currentPathArr = [
                    {
                        meta: {title: '主页'},
                        path: 'main/home',
                        name: 'home',
                    },
                ];
            } else if (currentPathObj.children && currentPathObj.children.length <= 1 && currentPathObj.name !== 'home') {
                currentPathArr = [
                    {
                        meta: {title: '主页'},
                        path: 'main/home',
                        name: 'home',
                    },
                    {
                        meta: {title: currentPathObj.meta.title},
                        path: '',
                        name: name,
                    },
                ];
            } else {
                let childObj = currentPathObj.children.filter((child: any) => {
                    return child.name === name;
                })[0];
                currentPathArr = [
                    {
                        meta: {title: '主页'},
                        path: 'main/home',
                        name: 'home',
                    },
                    {
                        meta: {title: currentPathObj.meta.title},
                        path: '',
                        name: '',
                    },
                    {
                        meta: {title: childObj.meta.title},
                        path: currentPathObj.path + '/' + childObj.path,
                        name: name,
                    },
                ];
            }
        }
        vm.$store.commit('app/setCurrentPath', currentPathArr);

        return currentPathArr;
    }

    openNewPage(vm: Vue, name: string | undefined, arg?: any, query?: any) {
        let pageOpenedList = vm.$store.state.app.pageOpenedList;
        let openedPageLen = pageOpenedList.length;
        let i = 0;
        let tagHasOpened = false;
        while (i < openedPageLen) {
            if (name === pageOpenedList[i].name) {
                vm.$store.commit('app/pageOpenedList', {
                    index: i,
                    arg: arg,
                    query: query,
                });
                tagHasOpened = true;
                break;
            }
            i++;
        }
        if (!tagHasOpened) {

            let tag = vm.$store.state.app.tagsList.filter((item: any) => {
                if (item.children) {
                    return name === item.children[0].name;
                } else {
                    return name === item.name;
                }
            });

            tag = tag[0];

            if (tag) {
                tag = tag.children ? tag.children[0] : tag;
                if (arg) {
                    tag.arg = arg;
                }
                if (query) {
                    tag.query = query;
                }
                vm.$store.commit('app/increaseTag', tag);
            }
        }
        vm.$store.commit('app/setCurrentPageName', name);
    }

    fullscreenEvent(vm: Vue) {
        vm.$store.commit('app/initCachePage');
        vm.$store.commit('app/updateMenuList');
    }

    extend(...args: any[]) {
        let options, name, src, srcType, copy, copyType, copyIsArray, clone,
            target = args[0] || {},
            i = 1,
            length = args.length,
            deep = false;
        if (typeof target === 'boolean') {
            deep = target;
            target = args[i] || {};
            i++;
        }
        if (typeof target !== 'object' && typeof target !== 'function') {
            target = {};
        }
        if (i === length) {
            target = this;
            i--;
        }
        for (; i < length; i++) {
            if ((options = args[i]) !== null) {
                for (name in options) {
                    src = target[name];
                    copy = options[name];
                    if (target === copy) {
                        continue;
                    }
                    srcType = Array.isArray(src) ? 'array' : typeof src;
                    if (deep && copy && ((copyIsArray = Array.isArray(copy)) || typeof copy === 'object')) {
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && srcType === 'array' ? src : [];
                        } else {
                            clone = src && srcType === 'object' ? src : {};
                        }
                        target[name] = this.extend(deep, clone, copy);
                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }
        return target;
    }

    getDecollator(num: number, decollator: string) {
        let temp: string = '';
        for (let i = 0; i < num * 2; i++) {
            temp += decollator;
        }
        return temp;
    }

    getTime(time: string) {
        return time ? time.replace('T', ' ').substr(0, 19) : '';
    }

    hasClass(el, cls) {
        if (!el || !cls) {
            return false;
        }
        if (cls.indexOf(' ') !== -1) {
            throw new Error('className should not contain space.');
        }
        if (el.classList) {
            return el.classList.contains(cls);
        } else {
            return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
        }
    }

    /* istanbul ignore next */
    addClass(el, cls) {
        if (!el) {
            return;
        }
        let curClass = el.className;
        const classes = (cls || '').split(' ');

        for (let i = 0, j = classes.length; i < j; i++) {
            const clsName = classes[i];
            if (!clsName) {
                continue;
            }

            if (el.classList) {
                el.classList.add(clsName);
            } else {
                if (!this.hasClass(el, clsName)) {
                    curClass += ' ' + clsName;
                }
            }
        }
        if (!el.classList) {
            el.className = curClass;
        }
    }

    /* istanbul ignore next */
    removeClass(el, cls) {
        if (!el || !cls) {
            return;
        }
        const classes = cls.split(' ');
        let curClass = ' ' + el.className + ' ';

        for (let i = 0, j = classes.length; i < j; i++) {
            const clsName = classes[i];
            if (!clsName) {
                continue;
            }

            if (el.classList) {
                el.classList.remove(clsName);
            } else {
                if (this.hasClass(el, clsName)) {
                    curClass = curClass.replace(' ' + clsName + ' ', ' ');
                }
            }
        }
        if (!el.classList) {
            el.className = this.trim(curClass);
        }
    }

    trim(string) {
        return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
    }

    guid() {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }

        return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
    }

    formatFileSize(size) {
        if (size < 1024) {
            return size + ' B';
        } else if (size >= 1024 && size < 1024 * 1024) {
            return Math.round((size / 1024) * 100) / 100 + ' KB';
        } else if (size >= 1024 * 1024 && size < 1024 * 1024 * 1024) {
            return Math.round((size / (1024 * 1014)) * 100) / 100 + ' MB';
        } else if (size >= 1024 * 1024 * 1024) {
            return Math.round((size / (1024 * 1024 * 1024)) * 100) / 100 + ' GB';
        }
    };

    prefixInteger(num: number, n: number) {
        return (Array(n).join('0') + num).slice(-n);
    }


    isNumber(val) {
        var regPos = /^\d+(\.\d+)?$/;
        var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/;
        return regPos.test(val) || regNeg.test(val);
    }

    async downloadWithToken(url: string, fileName: string, fileType: string) {
        const ajax = axios.create({
            baseURL: Config.remoteServiceBaseUrl,
            timeout: 30000,
            responseType: 'blob',
        });
        if (!!window.abp.auth.getToken()) {
            ajax.defaults.headers.common['Authorization'] = 'Bearer ' + window.abp.auth.getToken();
        }
        const response = await ajax.get(url);
        if (response.status === 200) {
            download(response.data, this.convert(fileName), fileType);
        } else {
            this.vm.$Message.error({
                background: true,
                content: '文件下载失败',
                duration: Config.duration,
            });
        }
    }

    convert(fileName) {
        return fileName.replace(/\//g, '／').replace(/\\/g, '＼').replace(/\*/g, '※').replace(/:/g, '：').replace(/"/g, '＂')
            .replace(/\?/g, '？').replace(/</g, '＜').replace(/>/g, '＞').replace(/\|/g, '┆');
    }

    convertDictionary(dictionaries: any[], values: string) {
        const valueArr = values.split(',');
        let result = [];
        for (const value of valueArr) {
            const dictionary = dictionaries.find(item => item.value === value);
            if (dictionary) {
                result.push(dictionary.name);
            }
        }
        return result.join(',');
    }
}

const util = new Util();
export default util;
